# 爬虫相关工具库
import json
import time

import pandas as pd
# from fake_useragent import UserAgent  # 随机生成UA的库
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import random

from data.Data import Data
from utils.YygeUtils import *


class GetUtils():
    config: None

    @staticmethod
    def ToUrl(driverData, url):
        driverData["driver"].get(url)
        driverData["num"] = 0  # 做参数限制
        time.sleep(2)
        return driverData
        # if driverData["num"] == 0:
        #     # 创建 User-Agent 对象
        #     UaClass = UserAgent()
        #
        #     # 生成随机的 User-Agent
        #     UA = UaClass.random
        #     headers = {
        #         'User-Agent': UA,
        #         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        #         'Accept-Encoding': 'gzip, deflate, sdch',
        #         'Accept-Language': 'en-US,en;q=0.8',
        #         'Cache-Control': 'max-age=0',
        #     }
        #     print("当前UA", UA)
        #     # 创建一个Chrome浏览器选项对象
        #     options = webdriver.ChromeOptions()
        #
        #     # 动态设置User Agent
        #     user_agent = UA
        #     options.add_argument('--user-agent=' + user_agent)
        #     driver = webdriver.Chrome(options=options)
        #
        #     # 获取所有打开的窗口句柄
        #     window_handles = driver.window_handles
        #
        #     # 选择一个窗口句柄切换到新的窗口
        #     new_window_handle = random.choice(window_handles)
        #     driver.switch_to.window(new_window_handle)
        #     driver.get(url)
        #     driverData["driver"] = driver
        #     driverData["num"] = 1
        #     return driverData
        # if driverData["num"] < 4:
        #     driverData["driver"].get(url)
        #     driverData["num"] = driverData["num"] + 1
        #     return driverData
        # else:
        #     # 创建 User-Agent 对象
        #     UaClass = UserAgent()
        #
        #     # 生成随机的 User-Agent
        #     UA = UaClass.random
        #     headers = {
        #         'User-Agent': UA,
        #         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        #         'Accept-Encoding': 'gzip, deflate, sdch',
        #         'Accept-Language': 'en-US,en;q=0.8',
        #         'Cache-Control': 'max-age=0',
        #     }
        #     print("当前UA", UA)
        #     # 创建一个Chrome浏览器选项对象
        #     options = webdriver.ChromeOptions()
        #
        #     # 动态设置User Agent
        #     user_agent = UA
        #     options.add_argument('--user-agent=' + user_agent)
        #     driver = webdriver.Chrome(options=options)
        #
        #     # 获取所有打开的窗口句柄
        #     window_handles = driver.window_handles
        #
        #     # 选择一个窗口句柄切换到新的窗口
        #     new_window_handle = random.choice(window_handles)
        #     driver.switch_to.window(new_window_handle)
        #     driver.get(url)
        #     driverData["driver"] = driver
        #     driverData["num"] = 0
        # return driverData

    # 获取列表详情的ID
    @staticmethod
    def GetDetailID(driver,name):
        targetFilePath = GetUtils.config.output.listPath.format(keyword=name)

        # 执行JS,JS将返回一个列表ID的JSON回来

        JSON = driver.execute_script(YygeUtils.getText(GetUtils.config.search.js) + f"\n return JSON.stringify({GetUtils.config.search.returnName})")
        YygeUtils.writeText(targetFilePath, json.dumps(json.loads(JSON), indent=2, sort_keys=True,ensure_ascii=False))
        print("------------- 已记录ID列表 -------------")
        return json.loads(JSON)

    @staticmethod
    def WaitLoad(newDriverData, url):
        try:
            # 跳转到目标页面
            newDriver = GetUtils.ToUrl(newDriverData, url)

            # 获取到浏览器驱动对象
            driver = newDriver["driver"]

            # # 先判断 网页是否存在校验
            # nc = driver.execute_script("return document.querySelector(\".nc_wrapper\")?1:0")
            # print("是否存在滑动校验", nc)
            # if nc == 1:  # 存在滑动校验
            #     time.sleep(2)  # 睡眠2秒
            #
            #     # 定位滑块元素
            #     slider = driver.find_element_by_class_name("nc_wrapper")
            #
            #     # 创建ActionChains对象并执行滑动操作
            #     action = ActionChains(driver)
            #     action.click_and_hold(slider).perform()  # 按住元素
            #     action.move_to_element_with_offset(slider, 460, 0).perform()  # 将鼠标移动到元素中心
            #     action.release().perform()  # 放开元素
            #
            #     # 睡眠1秒
            #     time.sleep(1)
            GetUtils.config.detail.get404.handle(driver) # 反爬滑动校验
            print("程序到这里 0 ")
            getDetail=YygeUtils.getText(GetUtils.config.detail.js).replace("[\"|?|\"]",json.dumps(GetUtils.config.output.column,ensure_ascii=False))
            # 强制异步加载 -- 用Js获取详情页的数据
            body = driver.execute_script(getDetail + "\n return JSON.stringify("+GetUtils.config.detail.returnName+")")
            body = json.loads(body)  # JSON转对象
            print("程序到这里 1 ")
            # 详情页内是否存ID为detailiframe的嵌套标签
            iframe = driver.find_elements_by_css_selector("#detailiframe")

            # 如果有的话
            if iframe:
                print("程序到这里 2 ")
                driver.switch_to_frame("detailiframe")  # 切换到iframe中

                # 执行JS 返回嵌套标签内的Body内容
                mainBody = driver.execute_script("return document.body.innerText")
                for obj in body:
                    print("程序到这里 3 ")
                    if obj["title"] == "招标正文":
                        obj["value"] = mainBody
                    else:
                        body.append({"title": "招标正文", "value": mainBody})
                driver.switch_to.default_content();  # 跳出iframe
            else:
                print("------- 未检测到iframe -------")
        except BaseException as e:
            print("报错了", e)
            time.sleep(10)  # 睡10秒钟
            # newDriverData["driver"].quit()
            newDriverData["num"] = 0
            # WaitLoad(newDriverData, url)
        finally:
            return body
            print("")
        return body

    @staticmethod
    def tryCatch(driverData, name, currentData, dataList, data):
        targetPath = GetUtils.config.output.listPath.format(keyword=name)  # target文件目录
        dataPath = GetUtils.config.output.dataPath.format(keyword=name) # data文件目录

        # 获取当前工作目录
        # workPath = os.getcwd()
        # allPath = workPath + targetPath
        # if os.path.exists(allPath):
        # else:
        #  return fun2(allPath)
        # 如果存在则获取数据 并转换成对象
        list = YygeUtils.fileExists(targetPath,
           lambda x: json.loads(YygeUtils.getText(targetPath)),
           lambda y: GetUtils.GetDetailID(driverData["driver"],name))
        try:
            # 轮询判断 网页元素中是否存在一个ID为wait的元素 - 轮询60秒
            # 如果有的话说明网页已经准备好了 - 可以抓取列表详情的ID值
            element = WebDriverWait(driverData["driver"], 60).until(
                EC.presence_of_element_located((By.ID, "wait"))
            )
            # 对话框出现后，进行相应的处理操作 --https://www.bidcenter.com.cn/news-270996373-1.html
            # 遍历对象
            for v in list:
                print("拿出列表:", v)
                if (v['id'] != "0" and v['id'] != 0):
                    if v['crawler'] == False:
                        id = v['id']
                        data['id'] = v['id']
                        print("正在抓取id", id)

                        # 等待详情页抓取完毕
                        data['body'] = GetUtils.WaitLoad(driverData, GetUtils.config.detail.url.format(id=id))
                        dataList.append(data)
                        data = {}  # 清空
                        YygeUtils.writeText(dataPath, json.dumps(dataList, ensure_ascii=False))

                        v['crawler'] = True
                        YygeUtils.writeText(targetPath, json.dumps(list, ensure_ascii=False))
                time.sleep(0.5)  # 0.5
        except TimeoutException:
            print("Element not found within the specified time.")
            time.sleep(1)
            # tryCatch(driverData,name,currentData,dataList,data)
        finally:
            currentData.list = dataList

            # overallData.append(currentData)-----------
            currentData = Data()
            toExcel = {}
            attribute = GetUtils.config.output.column
            for q in attribute:
                toExcel[q] = []
            for m in dataList:
                for p in attribute:
                    for text in m["body"]:
                        if text["title"] == p:
                            toExcel[p].append(text["value"])
                    # if q not in m:
                    #    m[q]=""
                    # print("看看M",m)
                    # toExcel[q].append(m[q])
            print("trycatch:finally")
            print("Hook:", toExcel)
            # 创建一个数据字典
            # tempData = {'姓名': ['张三', '李四', '王五'],
            #   '年龄': [25, 30, 35],
            #   '性别': ['男', '男', '女']}
            # 将数据字典转换为DataFrame对象
            df = pd.DataFrame(toExcel)
            dataList = []

            excelAllPath = os.getcwd()+GetUtils.config.output.excelPath.format(keyword = name)
            print(f"------>正在导出excel({excelAllPath})...")
            # 将DataFrame对象导出为Excel文件
            df.to_excel(excelAllPath)
        time.sleep(GetUtils.config.output.sleep)
        return currentData
